<?php
// +----------------------------------------------------------------------
// | Author: derek <693472824@qq.com> <http://www.bloveambition.com/>
// +----------------------------------------------------------------------
namespace Api\Controller;
use Think\Model;
use Api\Logic\UserLogic;

/**
 * 后台登录控制器
 * 
 * @author derek <693472824@qq.com>
 */
class WeChatApiController extends BaseController {

    /**
     * 初始化
     */
    public function _initialize () {
        
        // 引入WxPayPubHelper
        vendor('WxPayPubHelper.WxPayPubHelper');
        
        api('Server/loadConfig');
    }
    
    public function jsApiCall(){
        
        $orderID = I('order_id');
        $couponID = I('coupon_id');         //若不为空则表示用户选择的优惠券id
        
        // 使用jsapi接口
        $jsApi = new \JsApi_pub();
        
        /**
         *  步骤1：网页授权获取用户openid
         *  通过code获得openid
         */
        if (!isset($_GET['code'])) {
            
            $userID = $this->checkLogin('WeChatApi/jsApiCall', array('order_id'=>$orderID, 'coupon_id'=>$couponID));
            
            // 触发微信返回code码
            if(empty($couponID)){
                $redirectURL = C('WxPayConf_pub.JS_API_CALL_URL').'/order_id/'.$orderID.'.html';
            }else{
                $redirectURL = C('WxPayConf_pub.JS_API_CALL_URL').'/order_id/'.$orderID.'/coupon_id/'.$couponID.'.html';
            }
            
            $url = $jsApi->createOauthUrlForCode($redirectURL);

            Header("Location: $url");
            
        } else {
            
            // 获取code码，以获取openid
            $code = $_GET['code'];
            $jsApi->setCode($code);
            $openid = $jsApi->getOpenId();
        }
        
        // =========步骤2：使用统一支付接口，获取prepay_id============
        // 使用统一支付接口
        $unifiedOrder = new \UnifiedOrder_pub();
        
        // 设置统一支付接口参数
        // 设置必填参数
        // appid已填,商户无需重复填写
        // mch_id已填,商户无需重复填写
        // noncestr已填,商户无需重复填写
        // spbill_create_ip已填,商户无需重复填写
        // sign已填,商户无需重复填写
        $unifiedOrder->setParameter("openid", $openid); // 商品描述
        $unifiedOrder->setParameter("body", "北京天诺物业管理有限责任公司-帮工小哥服务费"); // 商品描述
         
        //生成自定义订单

        $userID = UserLogic::is_login();
        $map['user_id'] = $userID;
        $map['order_id'] = $orderID;
        $order = M('Orders')->where($map)->find();
        
        if(!empty($order) && $order['status'] == '4'){
        
            $coupon = D('User', 'Logic')->couponSolution($order['total'], $couponID);
            
            $totalFee = $order['total'];
            
            //可用优惠券不为空时，计算用户优惠后的总价
            //服务费须大于优惠金额，否则无法用微信支付
            if(!empty($coupon) && $totalFee>$coupon['money']){
                if(empty($coupon['minimum']) ||($totalFee > $coupon['minimum'])){
                    
                    $totalFee = $totalFee - $coupon['money'];
                    $order['rate_price'] = $totalFee;           //使用优惠券后价格
                    
                    $this->assign('coupon', $coupon);
                }
            }
        
            $totalFee = $totalFee * 100;
            
            //收费明细
            $chargeDetail = M('OrdersPrice')->where(array('order_id'=>$orderID))
                                ->getField('price_id,price_type,name,model,quantity,unit_price,total_price');
            $typeList = array();
            
            foreach ($chargeDetail as $key=>$val){
                
                $typeList[$val['price_type']][] = $val;
            }
        
            
            //生成自定义订单号
            $timeStamp = time();
            
            //因微信支付最小金额为 1分钱，所以若需支付费用等于 0时，不可使用微信支付
            if($totalFee < 1){
                
                $this->assign('totalFee', $totalFee);
                $totalFee = 1;
                
                //因此时不可使用微信支付，所以订单号是随机的，即使回调notify 接口，也不会修改任何订单状态
                $out_trade_no = $orderID.'-'.$order['address_id'].'-'.$order['detail_id'].'-'.$timeStamp;
            }else{
                $couponID = $coupon['coupon_id'] ? : '0';
                $out_trade_no = $orderID.'-'.$order['address_id'].'-'.$timeStamp.'-'.$totalFee.'-'.$couponID;
                
                $this->assign('totalFee', $totalFee);
            }
            
            //微信支付参数
            $unifiedOrder->setParameter("out_trade_no", $out_trade_no); // 商户订单号
            $unifiedOrder->setParameter("total_fee", $totalFee); // 总金额
            $unifiedOrder->setParameter("notify_url", C('WxPayConf_pub.NOTIFY_URL')); // 通知地址
            $unifiedOrder->setParameter("trade_type", "JSAPI"); // 交易类型
            
            $prepay_id = $unifiedOrder->getPrepayId();
            
            // =========步骤3：使用jsapi调起支付============
            $jsApi->setPrepayId($prepay_id);
            
            $jsApiParameters = $jsApi->getParameters();
            
            $this->assign('jsApiParameters', $jsApiParameters);
            
            $this->assign('order', $order);
            
            $this->assign('typeList', $typeList);
            $this->assign('detail', $chargeDetail);
            $this->display('weChatPay');
            
        }else{
        
            $this->error('参数异常','Orders/index');
        }
    }

    public function notify() {
        
        // 使用通用通知接口
        $notify = new \Notify_pub();
        
        // 存储微信的回调
        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $notify->saveData($xml);
        
        // 验证签名，并回应微信。
        // 对后台通知交互时，如果微信收到商户的应答不是成功或超时，微信认为通知失败，
        // 微信会通过一定的策略（如30分钟共8次）定期重新发起通知，
        // 尽可能提高通知的成功率，但微信不保证通知最终能成功。
        if ($notify->checkSign() == FALSE) {
            $notify->setReturnParameter("return_code", "FAIL"); // 返回状态码
            $notify->setReturnParameter("return_msg", "签名失败"); // 返回信息
        } else {
            $notify->setReturnParameter("return_code", "SUCCESS"); // 设置返回码
        }
        
        $returnXml = $notify->returnXml();
        
        // ==商户根据实际情况设置相应的处理流程，此处仅作举例=======
        
        // 以log文件形式记录回调信息
        $log_name = APP_PATH."/../Public/notify_url.log"; // log文件路径
        
        log_result($log_name, "【接收到的notify通知】:\n" . $xml . "\n");
        
        if ($notify->checkSign() == TRUE) {
            if ($notify->data["return_code"] == "FAIL") {
                
                log_result($log_name, "【通信出错】:\n" . $xml . "\n");
            } elseif ($notify->data["result_code"] == "FAIL") {
                
                log_result($log_name, "【业务出错】:\n" . $xml . "\n");
            } else {
                
                $out_trade_no = $notify->data["out_trade_no"];
                $dataArray = explode('-', $out_trade_no);

                $map['order_id'] = $dataArray[0];
                $map['address_id'] = $dataArray[1];
                $map['status'] = '4';
                
                $orderModel = M('Orders');
                
                $order = $orderModel->where($map)->find();
                
                //支付时使用优惠券，则修改优惠券状态为 2（已使用）
                if(!empty($dataArray[4])){
                    $couponModel = M('UserCoupon');
                    
                    $couponMap['coupon_id'] = $dataArray[4];
                    $couponMap['user_id'] = $order['user_id'];
                    
                    $coupon = $couponModel->where($couponMap)->find();
                    
                    if(!empty($coupon)){
                        $couponData['beneficiary'] = $order['user_id'];
                        $couponData['address'] = $order['address_id'];
                        $couponData['use_time'] = NOW_TIME;
                        $couponData['status'] = '2';
                        $couponModel->where($couponMap)->save($couponData);
                        
                        //计算订单交易额 = 实际支付费用 + 优惠券金额 * 补贴比例
                        $subsidy = C('SUBSIDY_PROPORTION');
                        $subsidy = is_numeric($subsidy) ? $subsidy : '30';
                        $turnover = $dataArray['3']/100 + $coupon['money'] * $subsidy/100;          
                    }
                }
                
                //修改订单状态
                $data['status'] = '6';
                $data['coupon_id'] = $dataArray['4'] ? : '0';
                $data['rate_price'] = $dataArray['3']/100;
                $data['turnover'] = !empty($turnover) ? $turnover : $dataArray['3']/100;
                $data['pay_type'] = '1';
                
                $result = $orderModel->where($map)->save($data);
                
                //修改小哥账户余额
                //完整的公式（李经理20160706提供）：
                // 每一笔订单的交易额=用户实际支付的金额（含在线支付和线下现金） + （优惠券抵扣掉的金额*后台设置的补贴比例）
                // 闲散小哥的余额：
                //    如果是线上交易，每一笔交易，小哥余额增加：交易额*给小哥的绩效比例
                //    如果是线下交易，每一笔交易，小哥余额减少：交易额*（1-给小哥的绩效比例）
                // 自有小哥的账户余额 = 该小哥完成的所有订单的交易额 * 后台设置的绩效比例
                
                $workerModel = M('Worker');
                $workerMap['worker_id'] = $order['worker_id'];
                $worker = $workerModel->where($workerMap)->find();
                
                //自有团队成员
                if($worker['member_type'] == '1'){
                    $proportion = C('TEAM_PROPORTION') ? : '80';
                }elseif ($worker['member_type'] == '2'){
                    $proportion = C('COMMISSION_PROPORTION') ? : '70';
                }else{
                    $proportion = '0';
                }
                
                $balance = round($data['turnover'] * $proportion/100, 2);
                $workerModel->where($workerMap)->setInc('balance', $balance);
                
                //记录小哥账户余额资金变动情况
                $cashData['worker_id'] = $order['worker_id'];
                $cashData['op_type'] = '3';
                $cashData['order_id'] = $order['order_id'];
                $cashData['previous'] = $worker['balance'];
                $cashData['cash'] = $balance;
                $cashData['balance'] = $worker['balance'] + $balance;
                $cashData['status'] = '1';
                $cashData['create_time'] = NOW_TIME;
                $cashData['admin_id'] = '0';
                
                M('WorkerCash')->add($cashData);
                
                
                log_result($log_name, "【支付成功】:\n" . $xml .'；修改支付结果：'.$result. "\n");
                log_result($log_name, "【支付成功】:\n" . $xml . "\n");
            }
        }
    }

    /**
     * 获取 jsApi 配置信息
     */
    public function getApiConfig(){
        
        $ajaxResult = array('status'=>0, 'msg'=>'', 'info'=>'');
        
        $fullURL = I('currentURL');
        
        if(empty($fullURL)){
            
            $ajaxResult['msg'] = '参数错误';
            $this->ajaxReturn($ajaxResult);
        }
        
        //生成上传图片时需要的参数
        $appID = C('WxPayConf_pub.APPID');
        $timeStamp = NOW_TIME;
        $nonceStr = \Org\Util\String::randString(16);
        
        $signature = api('Util/getSignature', array($nonceStr, $timeStamp, $fullURL));
        $token = api('Util/getToken');
        
        $data['appid'] = C('WxPayConf_pub.APPID');
        $data['timestamp'] = $timeStamp;
        $data['nonceStr'] = $nonceStr;
        $data['signature'] = $signature;
        $data['token'] = $token;
        
        $ajaxResult['status'] = '1';
        $ajaxResult['info'] = $data;
        
        $this->ajaxReturn($ajaxResult);
    }
    
    /**
     * 现金支付
     */
    public function payCash(){
        
        $userID = UserLogic::is_login();
        $orderID = I('order_id');
        $couponID = I('coupon_id');
        
        if(empty($userID)){
            
            $this->result['status'] = '-201';
        }else if(empty($orderID) || !is_numeric($orderID)){
            
            $this->result['status'] = '0';
        }else{
            
            $orderModel = M('Orders');
            
            $map['order_id'] = $orderID;
            $map['user_id'] = $userID;
            $map['status'] = '4';       //服务结束待收费
            
            $order = $orderModel->where($map)->find();
            
            $data['status'] = '5';
            
            if(!empty($couponID)){
                
                $couponModel = M('UserCoupon');
                
                $couponMap['user_id'] = $userID;
                $couponMap['coupon_id'] = $couponID;
                $coupon = $couponModel->where($couponMap)->find();
                
                if(!empty($coupon)){
                    
                    $couponData['beneficiary'] = $order['user_id'];
                    $couponData['address'] = $order['address_id'];
                    $couponData['use_time'] = NOW_TIME;
                    $couponData['status'] = '2';
                    $couponModel->where($couponMap)->save($couponData);
                    
                    //计算订单交易额 = 实际支付费用 + 优惠券金额 * 补贴比例
                    $subsidy = C('SUBSIDY_PROPORTION');
                    $subsidy = is_numeric($subsidy) ? $subsidy : '30';
                    
                    $data['coupon_id'] = $couponID;
                    $data['rate_price'] = $order['total'] - $coupon['money'];
                    $data['turnover'] = $data['rate_price'] + round($coupon['money'] * $subsidy/100, 2);        //交易额 = 实际支付金额 + 优惠券金额 * 后台设置比例SUBSIDY_PROPORTION 
                    $data['pay_type'] = '2';
                }
            }else{
                $data['coupon_id'] = '0';
                $data['rate_price'] = $order['total'];
                $data['turnover'] = $data['rate_price'];        //交易额 = 实际支付金额 + 优惠券金额 * 后台设置比例SUBSIDY_PROPORTION
                $data['pay_type'] = '2';
            }
            
            $result = $orderModel->where($map)->save($data);
            
            if($result){
                $this->result['status'] = '1';
            }else{
                $this->result['status'] = '0';
            }
        }
        
        $this->ajaxReturn($this->result);
    }
}
